<template>
	<div class="task-details-container" v-loading.fullscreen.lock="fullscreenLoading">
		<div style="margin: 2% auto">
			<el-divider content-position="center"><h2>任务详情</h2></el-divider>
		</div>
		<div class="task-details-content">
			<el-row :gutter="20" class="task-details-row">
				<el-col :span="19">
					<el-card class="task-details-card">
						<el-table
							:show-header="false"
							:data="[
								{ key1: '任务名称', value1: task.name, key2: '任务介绍', value2: task.task_description },
								{ key1: '靶点名称', value1: task.target_name, key2: '筛选库介绍', value2: task.library_description },
								{ key1: '提交时间', value1: task.submitted, key2: '完成时间', value2: task.completed },
								{ key1: 'AI模型', value1: task.model_name || '/', key2: 'AI模型介绍', value2: task.model_description },
								{ key1: '任务状态', value1: task.status, key2: '任务进度', value2: task.progress + '%' }
							]"
							style="width: 100%"
						>
							<el-table-column prop="key1" label="属性" width="100"></el-table-column>
							<el-table-column label="值">
								<template v-slot="scope">
									<template v-if="scope.row.key1 === '任务状态'">
										<el-tag size="small" :type="task.status === '已完成' ? 'success' : 'warning'">{{ scope.row.value1 }}</el-tag>
									</template>
									<template v-else-if="scope.row.key2 === '任务进度'">
										<el-progress :percentage="task.progress"></el-progress>
									</template>
									<template v-else>
										{{ scope.row.value1 }}
									</template>
								</template>
							</el-table-column>
							<el-table-column prop="key2" label="属性" width="100"></el-table-column>
							<el-table-column prop="value2" label="值">
								<template v-slot="scope">
									<template v-if="scope.row.key2 === '任务进度'">
										<el-progress :percentage="task.progress"></el-progress>
									</template>
									<template v-else>
										{{ scope.row.value2 }}
									</template>
								</template>
							</el-table-column>
						</el-table>
					</el-card>
				</el-col>
				<el-col :span="5">
					<div id="container-01" class="mol-container"></div>
					<!-- 显示蛋白的pdb结构 -->
					<div class="mol-description" v-if="has_pdb">
						<el-tag type="info" size="medium">ESM-fold预测结构</el-tag>
					</div>
				</el-col>
			</el-row>
		</div>

		<div id="charts-container" class="charts-section" v-if="totalCompounds > 0">
			<div style="margin: 2% auto">
				<el-divider content-position="center"><h2>筛选结果概览</h2></el-divider>
			</div>
			<!-- 			<el-row :gutter="5">
				<el-col :span="4" style="width: 20%">
					<div ref="chart1" style="height: 450px" />
				</el-col>
				<el-col :span="4" style="width: 20%">
					<div ref="chart2" style="height: 450px" />
				</el-col>
				<el-col :span="4" style="width: 20%">
					<div ref="chart3" style="height: 450px" />
				</el-col>
				<el-col :span="4" style="width: 20%">
					<div ref="chart4" style="height: 450px" />
				</el-col>
				<el-col :span="4" style="width: 20%">
					<div ref="heatmap" style="height: 400px" />
				</el-col>
			</el-row> -->

			<el-row :gutter="5">
				<el-col :span="6">
					<div ref="chart1" style="height: 450px" />
				</el-col>
				<el-col :span="6">
					<div ref="chart2" style="height: 450px" />
				</el-col>
				<el-col :span="6">
					<div ref="chart3" style="height: 450px" />
				</el-col>
				<el-col :span="6">
					<div ref="chart4" style="height: 450px" />
				</el-col>
			</el-row>

			<!--      <el-row :gutter="20" style="margin-top: 20px;">
        <el-col :span="24">
          <div ref="heatmap" style="height: 400px;" />
        </el-col>
      </el-row> -->
		</div>
		<div class="buttons" style="display: flex; align-items: flex-end; justify-content: flex-end">
			<!-- 下载结果按钮 -->
			<el-button type="primary" round icon="el-icon-printer" @click="downloadResults" :disabled="compounds.length === 0">下载结果</el-button>

			<!-- 生成报告按钮 -->
			<el-button type="success" round icon="el-icon-document" @click="downloadpdf" :disabled="compounds.length === 0">生成报告</el-button>

			<!-- 联系技术支持按钮 -->
			<el-button type="info" round icon="el-icon-phone-outline" @click="contactSupport">联系技术支持</el-button>
		</div>

		<div class="table-section" v-if="totalCompounds > 0">
			<div style="margin: 1% auto">
				<el-divider content-position="center">
					<h2>结果详情</h2>
				</el-divider>

				<!-- 添加视图切换按钮 -->
				<div style="text-align: right; margin-bottom: 1em">
					<el-radio-group v-model="viewMode" size="mini">
						<el-radio-button label="table">
							<i class="el-icon-tickets"></i>
						</el-radio-button>
						<el-radio-button label="card">
							<i class="el-icon-picture-outline-round"></i>
						</el-radio-button>
					</el-radio-group>
				</div>
			</div>

			<!-- 表格视图 -->
			<div class="table-section" v-if="viewMode === 'table' && totalCompounds > 0">
				<el-row>
					<el-col :span="24">
						<el-table :data="paginatedCompounds" style="width: 100%" height="600" stripe>
							<el-table-column prop="compound_id" label="化合物ID"></el-table-column>
							<el-table-column prop="smile" label="化合物SMILE" width="400"></el-table-column>
							<el-table-column prop="formula" label="分子式"></el-table-column>
							<el-table-column prop="logp" label="Log P" sortable :formatter="(row) => parseFloat(row.logp).toFixed(2)"></el-table-column>
							<el-table-column prop="psa" label="极性表面积" sortable :formatter="(row) => parseFloat(row.psa).toFixed(2)"></el-table-column>
							<el-table-column prop="rotable_bond" label="可旋转键数" sortable></el-table-column>
							<el-table-column prop="weight" label="分子量" sortable :formatter="(row) => parseFloat(row.weight).toFixed(2)"></el-table-column>
							<el-table-column prop="affinity_score" label="预测评分" sortable></el-table-column>
							<el-table-column label="操作" width="230">
								<template v-slot="scope">
									<el-tooltip content="查看详情" placement="top">
										<el-button icon="el-icon-view" circle @click="viewCompound(scope.row)" size="medium"></el-button>
									</el-tooltip>
									<el-tooltip content="下载化合物" placement="top">
										<el-button icon="el-icon-download" circle @click="downloadCompound(scope.row)" size="medium"></el-button>
									</el-tooltip>
									<el-tooltip content="查看ADMET预测结果" placement="top">
										<el-button icon="el-icon-data-analysis" circle @click="viewADMET(scope.row)" size="medium"></el-button>
									</el-tooltip>
									<el-tooltip content="查询相似化合物" placement="top">
										<el-button icon="el-icon-search" circle @click="findSimilarCompounds(scope.row)" size="medium"></el-button>
									</el-tooltip>
								</template>
							</el-table-column>
						</el-table>
					</el-col>
				</el-row>
			</div>

			<!-- 卡片视图 -->
			<div class="card-section" v-if="viewMode === 'card' && totalCompounds > 0">
				<el-row :gutter="20" justify="start">
					<el-col :span="6" v-for="compound in paginatedCompounds" :key="compound.compound_id">
						<el-card shadow="hover">
							<div style="display: flex; justify-content: space-between; align-items: center">
								<div>
									<span style="font-size: 14px">ID: {{ compound.compound_id }}</span>
								</div>
								<!-- Score 部分，靠右对齐 -->
								<div class="score-container" style="font-size: 14px; text-align: right">
									Score:
									<el-tag type="success" size="mini">{{ compound.affinity_score }}</el-tag>
								</div>
							</div>
							<img :src="generate2DImageCard(compound.smile)" alt="化合物图片" style="width: 100%; height: 150px; object-fit: fill" />
							<div style="padding: 5px">
								<!-- SMILES 部分 -->
								<div style="font-size: 14px; text-align: left">
									SMILES:
									<el-input type="textarea" :rows="2" :value="compound.smile" readonly class="smiles-text" />
								</div>
							</div>
							<div style="text-align: right; margin-top: 10px">
								<el-tooltip content="查看详情" placement="top">
									<el-button icon="el-icon-view" circle @click="viewCompound(compound)" size="medium"></el-button>
								</el-tooltip>
								<el-tooltip content="下载化合物" placement="top">
									<el-button icon="el-icon-download" circle @click="downloadCompound(compound)" size="medium"></el-button>
								</el-tooltip>
								<el-tooltip content="查看ADMET预测结果" placement="top">
									<el-button icon="el-icon-data-analysis" circle @click="viewADMET(compound)" size="medium"></el-button>
								</el-tooltip>
								<el-tooltip content="查询相似化合物" placement="top">
									<el-button icon="el-icon-search" circle @click="findSimilarCompounds(compound)" size="medium"></el-button>
								</el-tooltip>
							</div>
						</el-card>
					</el-col>
				</el-row>
			</div>
		</div>

		<el-empty v-else description="暂无结果, 该任务正在执行中。"></el-empty>
		<div class="pagination" v-if="totalCompounds > 0">
			<el-pagination
				@current-change="handlePageChange"
				@size-change="handleSizeChange"
				:current-page="currentPage"
				:page-size="pageSize"
				:page-sizes="[8, 16, 24]"
				layout="sizes, prev, pager, next, jumper"
				:total="totalCompounds"
			></el-pagination>
		</div>

		<!-- 相似化合物 dialog，卡片视图 -->
		<el-dialog :visible.sync="similarCompoundsDialogVisible" title="相似化合物(基于Tanimoto相似度，推荐20个，数据来源于PubChem和ChEMBL)" width="60%">
			<div v-if="simi_loading">
				<el-row :gutter="10" justify="start">
					<el-col :span="8" v-for="n in 6" :key="n">
						<el-skeleton animated>
							<el-skeleton-item variant="image" style="width: 80px; height: 80px; margin: 5px auto"></el-skeleton-item>
							<el-skeleton-item variant="text" style="width: 80px; height: 20px; margin-top: 5px"></el-skeleton-item>
							<el-skeleton-item variant="button" style="width: 30px; height: 30px; margin: 5px auto"></el-skeleton-item>
						</el-skeleton>
					</el-col>
				</el-row>
			</div>

			<div v-else style="max-height: 600px; overflow-y: auto; padding-right: 10px">
				<el-row :gutter="20" justify="start">
					<el-col :span="6" v-for="(compound, index) in similarCompounds" :key="`${compound.smile}-${index}`">
						<el-card shadow="hover" >
							<div style="font-size: 12px; display: flex; justify-content: space-between; align-items: center">
								<span>相似度:</span>
							<el-tag type="success" size="mini">{{ compound.similarity.toFixed(2) }}</el-tag>

							</div>

							<img :src="generate2DImageCard(compound.smile)" alt="化合物图片" style="width: 120px; height: 120px; margin: 10px auto; display: block" />
							<div style="font-size: 12px; text-align: center; margin-top: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
								SMILES: {{ compound.smile }}
							</div>
							<div style="text-align: right; margin-top: 10px">
								<el-tooltip content="查看详情" placement="top">
									<el-button icon="el-icon-view" circle @click="viewCompound(compound)" size="mini"></el-button>
								</el-tooltip>
							</div>
						</el-card>
					</el-col>
				</el-row>
			</div>
		</el-dialog>

		<el-dialog :visible.sync="compoundDialogVisible" width="50%">
			<div class="compound-info">
				<el-row :gutter="5">
					<el-col :span="8">
						<!-- <span>化合物结构信息</span> -->
						<div v-if="svgContent" v-html="svgContent"></div>
					</el-col>
					<el-col :span="16">
						<el-table
							:show-header="false"
							:data="[
								{ key: 'ID', value: selectedCompound.compound_id },
								{ key: 'Drug Type', value: 'Small molecule' },
								{ key: 'Molecular Formula', value: selectedCompound.formula },
								{ key: 'Molecular Weight', value: selectedCompound.weight },
								{ key: 'InChI', value: selectedCompound.InChI },
								{ key: 'InChI Key', value: selectedCompound.InChI_Key },
								{ key: 'SMILES', value: selectedCompound.smiles }
							]"
							style="width: 100%"
						>
							<el-table-column prop="key" label="属性" width="200"></el-table-column>
							<el-table-column prop="value" label="值"></el-table-column>
						</el-table>
					</el-col>
				</el-row>
			</div>
		</el-dialog>
		<el-dialog :visible.sync="admetDialogVisible" title="ADMET预测结果" width="60%">
			<div v-if="admet_loading">
				<!-- 骨架屏 -->
				<el-skeleton :rows="4" animated>
					<template #template>
						<el-skeleton-item variant="text" style="width: 80%; margin-bottom: 10px"></el-skeleton-item>
						<el-skeleton-item variant="rect" style="width: 100%; height: 20px"></el-skeleton-item>
					</template>
				</el-skeleton>
			</div>
			<div v-else>
				<el-tabs type="card">
					<el-tab-pane v-for="(groupData, groupName) in admetData" :key="groupName" :label="groupName">
						<template #label>
							<div :style="getCardStyle(groupName)">
								<i :class="getCardIcon(groupName)" style="margin-right: 8px"></i>
								{{ groupName }}
							</div>
						</template>
						<el-table :data="Object.entries(groupData)" stripe>
							<el-table-column prop="0" label="属性" width="300"></el-table-column>
							<el-table-column label="值">
								<template slot-scope="scope">
									<div style="display: flex; align-items: center">
										<span v-html="scope.row[1].value"></span>
										<el-tooltip v-if="scope.row[1].annotation" :content="scope.row[1].annotation" placement="top" effect="dark">
											<el-button type="text" icon="el-icon-info" style="margin-left: 8px; cursor: pointer"></el-button>
										</el-tooltip>
									</div>
								</template>
							</el-table-column>
						</el-table>
					</el-tab-pane>
				</el-tabs>
			</div>

			<span slot="footer" class="dialog-footer" style="text-align: center">
				<p style="font-size: 12px; color: #888">
					Powered by
					<a href="http://www.swissadme.ch/index.php#" target="_blank" style="text-decoration: none; color: #888">SwissADME</a>
				</p>
			</span>
		</el-dialog>
	</div>
</template>

<script>
import axios from 'axios';
import { Message, MessageBox } from 'element-ui';
import * as echarts from 'echarts';
import { nextTick } from 'vue';
import { jsPDF } from 'jspdf';
import html2canvas from 'html2canvas';
import 'jspdf-autotable';
import { saveAs } from 'file-saver';
import NProgress from 'nprogress';

export default {
	name: 'TaskDetailsView',
	data() {
		return {
			task: {
				id: '',
				name: '',
				submitted: '',
				completed: '',
				status: '',
				progress: 0
			},
			compounds: [],
			currentPage: 1,
			pageSize: 8,
			totalCompounds: 0,
			dataList: [],
			compoundDialogVisible: false,
			svgContent: '',
			selectedCompound: {},
			fullscreenLoading: false,
			similarityMatrix: [],
			admetData: [],
			admetDialogVisible: false,
			admet_loading: false,
			simi_loading: false,
			has_pdb: false,
			viewMode: 'table', // 默认视图模式
			similarCompounds: [],
			similarCompoundsDialogVisible: false,
			admetCache: {},
			simicache: {} // 用于缓存已请求的化合物数据
		};
	},
	computed: {
		paginatedCompounds() {
			const start = (this.currentPage - 1) * this.pageSize;
			const end = start + this.pageSize;
			return this.compounds.slice(start, end);
		}
	},
	mounted() {
		const taskId = this.$route.params.taskId;
		this.fetchTaskDetails(taskId);
	},
	methods: {
		findSimilarCompounds(compound) {
			this.similarCompoundsDialogVisible = true;
			const cacheKey = compound.smile; // 使用化合物的SMILES作为缓存键
			// 检查缓存中是否已经存在相应的数据
			if (this.simicache[cacheKey]) {
				this.similarCompounds = this.simicache[cacheKey]; // 从缓存加载数据
				this.simi_loading = false; // 关闭加载状态
				return;
			}
			this.simi_loading = true; // 启用加载状态
			this.similarCompounds = []; // 清空上一次的结果
			axios
				.post('/api/compounds/similar', {
					target_smiles: compound.smile
				})
				.then((response) => {
					this.similarCompounds = response.data;
					// 将结果存入缓存
					this.simicache[cacheKey] = response.data;
				})
				.catch((error) => {
					console.error('Failed to fetch similar compounds:', error);
					this.$message.error('查询相似化合物失败');
				})
				.finally(() => {
					this.simi_loading = false; // 请求完成，关闭加载状态
				});
		},

		generate2DImageCard(smile) {
			if (typeof RDKitModule === 'undefined') {
				console.error('RDKit.js尚未加载');
				return '';
			}
			try {
				const mol = RDKitModule.get_mol(smile);
				const svg = mol.get_svg();
				mol.delete();
				return 'data:image/svg+xml;base64,' + btoa(svg);
			} catch (error) {
				console.error('生成2D结构图时出错:', error);
				return '';
			}
		},
		showpdb(task_id, target_name) {
			let element = document.querySelector('#container-01');
			let config = {};
			let viewer = $3Dmol.createViewer(element, config);
			viewer.setBackgroundColor('white');

			// 开始加载前显示加载动画
			const loading = this.$loading({
				target: element,
				text: '结构预测中...',
				background: 'rgba(255, 255, 255, 0.8)'
			});

			// 设置请求路径以调用后端API获取PDB文件内容
			let pdbUri = '/api/predict';

			axios
				.post(
					pdbUri,
					{
						task_id: task_id,
						target_name: target_name
					},
					{
						headers: {
							'Content-Type': 'application/json'
						}
					}
				)
				.then((response) => {
					let data = response.data;
					let v = viewer;
					v.addModel(data, 'pdb');
					v.setStyle({}, { cartoon: { color: 'spectrum' } });
					v.zoomTo();
					v.render();
					v.zoom(1.2, 1000);
					this.has_pdb = true;
				})
				.catch((error) => {
					console.error('Failed to load PDB: ', error);

					// 设置 element 的样式来实现大致的垂直居中效果
					element.style.fontSize = '16px'; // 设置字体大小
					element.style.color = '#606266'; // 设置字体颜色（例如红色）

					// 定义用于显示图标的HTML内容
					const icon413 = '<span style="color: #d9534f;">&#x26A0;️</span>'; // 红色警告图标
					const icon400 = '<span style="color: #f0ad4e;">&#x26A0;️</span>'; // 黄色警告图标
					const iconDefault = '<span style="color: #5bc0de;">&#x231B;</span>'; // 蓝色等待图标

					// 根据错误类型设置 element 的内容和样式
					if (error.response && error.response.status === 413) {
						element.innerHTML = `${icon413} 序列长度超过最大支持的限制（400个氨基酸）。请尝试使用更短的序列进行预测。`;
						element.style.color = '#d9534f'; // 红色字体用于错误提示
					} else if (error.response && error.response.status === 400) {
						element.innerHTML = `${icon400} 请求参数不完整（缺少 task_id 或 target_name）。请检查后重新提交。`;
						element.style.color = '#f0ad4e'; // 黄色字体用于警告信息
					} else {
						element.innerHTML = `${iconDefault} 结构预测正在进行中，请耐心等待片刻。`;
						element.style.color = '#5bc0de'; // 蓝色字体用于信息提示
					}

					const molContainer = document.querySelector('.mol-container');
					// 并相应地调整高度
					molContainer.style.height = '300px';
					// 使用 CSS 样式调整 flex 布局
					molContainer.style.display = 'flex';
					molContainer.style.alignItems = 'center';
					molContainer.style.justifyContent = 'center';
				})

				.finally(() => {
					// 移除加载动画
					loading.close();
				});
		},

		getCardStyle(groupName) {
			// Define colors for different ADMET categories
			const categoryColors = {
				'Medicinal Chemistry': 'color: #8B0000', // Dark Red for Medicinal Chemistry
				Druglikeness: 'color: #FF8C00', // Dark Orange for Druglikeness
				Pharmacokinetics: 'color: #4682B4', // Steel Blue for Pharmacokinetics
				'Water Solubility': 'color: #1E90FF', // Dodger Blue for Water Solubility
				Lipophilicity: 'color: #32CD32', // Lime Green for Lipophilicity
				'Physicochemical Properties': 'color: #8A2BE2' // Blue Violet for Physicochemical Properties
			};
			return categoryColors[groupName] || 'color: #000'; // Default color is black
		},
		getCardIcon(groupName) {
			// Define icons for different ADMET categories
			const categoryIcons = {
				'Medicinal Chemistry': 'el-icon-edit', // Edit icon for Medicinal Chemistry
				Druglikeness: 'el-icon-star-on', // Star icon for Druglikeness
				Pharmacokinetics: 'el-icon-share', // Share icon for Pharmacokinetics
				'Water Solubility': 'el-icon-water', // Water icon for Water Solubility
				Lipophilicity: 'el-icon-refresh', // Refresh for Lipophilicity
				'Physicochemical Properties': 'el-icon-setting' // Setting icon for Physicochemical Properties
			};
			return categoryIcons[groupName] || 'el-icon-circle-check'; // Default icon
		},
		viewADMET(compound) {
			this.admetDialogVisible = true;
			this.admet_loading = true;

			// Initialize cache object if it does not exist
			if (!this.admetCache) {
				this.admetCache = {};
			}

			const cacheKey = compound.smile;

			// Check if data is already in the cache
			if (this.admetCache[cacheKey]) {
				this.admetData = this.admetCache[cacheKey];
				this.admet_loading = false;
				return;
			}

			// Start the progress bar
			NProgress.start();

			axios
				.post('/api/get_admet', {
					SMILES: [compound.smile] // 提供的SMILES参数，作为请求体
				})
				.then((response) => {
					if (response.data) {
						// Cache the data
						this.admetCache[cacheKey] = response.data;
						// Assign the data to admetData
						this.admetData = response.data;
					} else {
						console.error('Unexpected response format', response);
					}
					this.admet_loading = false;
				})
				.catch((error) => {
					console.error('Error fetching ADMET data', error);
					this.$message.error('Failed to fetch ADMET data. Please try again.');
					this.admet_loading = false;
				})
				.finally(() => {
					// Stop the progress bar
					NProgress.done();
				});
		},
		async fetchTaskDetails(taskId) {
			try {
				this.fullscreenLoading = true;
				const response = await axios.get(`/api/tasks/details/${taskId}`);
				const taskDetails = response.data;
				this.task = {
					id: taskDetails.task_id,
					name: taskDetails.task_name,
					submitted: taskDetails.create_time,
					completed: taskDetails.complete_time,
					status: taskDetails.task_status === 'completed' ? '已完成' : '进行中',
					progress: taskDetails.task_status === 'completed' ? 100 : 50,
					library_description: taskDetails.library_description,
					target_name: taskDetails.target_name,
					library_name: taskDetails.library_name,
					task_description: taskDetails.task_description,
					model_name: taskDetails.model_name,
					model_description: taskDetails.model_description
				};
				if (taskDetails.results) {
					this.compounds = taskDetails.results;
					this.totalCompounds = taskDetails.results.length;
					// this.similarityMatrix = this.completeMatrix(taskDetails.tomito);
					this.dataList = taskDetails.results.map((result) => result.affinity_score);
					this.logpvalues = taskDetails.results.map((result) => result.logp);
					this.psavalues = taskDetails.results.map((result) => result.psa);
					this.rotable_bondvalues = taskDetails.results.map((result) => result.rotable_bond);
					this.weightvalues = taskDetails.results.map((result) => result.weight);
					if (this.totalCompounds > 0) {
						await nextTick();
						this.initCharts();
						// this.initHeatmap();
						this.showpdb(taskDetails.task_id, taskDetails.target_name);
					}
				}
			} catch (error) {
				console.error('获取任务详情时出错:', error);
			} finally {
				this.fullscreenLoading = false;
			}
		},
		completeMatrix(matrix) {
			const n = matrix.length;

			// 创建结果矩阵并初始化为0
			const result = Array.from({ length: n }, () => Array(n).fill(0));

			// 遍历上三角矩阵并将值填充到完整矩阵中
			for (let i = 0; i < n; i++) {
				for (let j = i; j < n; j++) {
					result[i][j] = matrix[i][j];
					if (i !== j) {
						result[j][i] = matrix[i][j]; // 利用对称性填充下三角部分
					}
				}
			}

			return result;
		},

		handlePageChange(page) {
			this.currentPage = page;
		},
		handleSizeChange(size) {
			this.pageSize = size;
			this.currentPage = 1;
		},
		viewCompound(compound) {
			this.selectedCompound = compound;
			this.compoundDialogVisible = true;
			this.generate2DImage(compound.smile);
		},
		contactSupport() {
			window.location.href = 'mailto:daydayupzzl@163.com?subject=技术支持请求&body=请详细描述您的问题';
		},
		generate2DImage(smile) {
			if (typeof RDKitModule === 'undefined') {
				console.error('RDKit.js尚未加载');
				return;
			}
			try {
				const mol = RDKitModule.get_mol(smile);
				const svg = mol.get_svg();
				this.svgContent = svg;
				this.selectedCompound['InChI'] = RDKitModule.get_inchikey_for_inchi(mol.get_inchi());

				this.selectedCompound['InChI_Key'] = mol.get_inchi();

				this.selectedCompound['smiles'] = mol.get_smiles();

				mol.delete();
			} catch (error) {
				console.error('生成2D结构图时出错:', error);
			}
		},
		downloadCompound(compound) {
			try {
				const filename = `Compound_${compound.compound_id}.txt`;
				const content = `ID: ${compound.compound_id}\nSMILES: ${compound.smile}\nFormula: ${compound.formula}\nAffinity Score: ${compound.affinity_score}\nLog P: ${compound.logp}\nPSA: ${compound.psa}\nRotatable Bond: ${compound.rotable_bond}\nWeight: ${compound.weight}`;

				// 创建并下载文本文件
				const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
				saveAs(blob, filename);
			} catch (error) {
				console.error('下载化合物时出错:', error);
			}
		},
		async downloadpdf() {
			try {
				const doc = new jsPDF('p', 'mm', 'a4');

				// Set font to support Chinese characters
				doc.setFont('helvetica', 'normal');
				doc.setFontSize(20);
				doc.text('Task Details Report', 105, 15, { align: 'center' });
				doc.setFontSize(12);
				doc.text(`Submitted Time: ${this.task.submitted}`, 14, 39);
				doc.text(`Completed Time: ${this.task.completed || '/'}`, 14, 46);

				// Task summary table
				const taskSummaryData = [['AI Model', this.task.model_name]];
				doc.autoTable({
					startY: 70,
					head: [['Attribute', 'Value']],
					body: taskSummaryData,
					styles: { cellWidth: 'wrap', font: 'helvetica' },
					columnStyles: {
						1: { cellWidth: 'auto' }
					}
				});

				// Adding charts to the PDF
				const chartsRefs = [this.$refs.chart1, this.$refs.chart2, this.$refs.chart3, this.$refs.chart4, this.$refs.heatmap];
				for (let i = 0; i < chartsRefs.length; i++) {
					if (chartsRefs[i]) {
						const canvas = await html2canvas(chartsRefs[i], { scale: 3 }); // Increase the scale to improve resolution
						const imgData = canvas.toDataURL('image/png');
						doc.addPage();
						doc.addImage(imgData, 'PNG', 10, 10, 190, 100);
					}
				}

				// Results table
				const compoundsData = this.compounds.map((compound) => [
					compound.compound_id,
					compound.smile,
					compound.formula,
					compound.logp,
					compound.psa,
					compound.rotable_bond,
					compound.weight,
					compound.affinity_score
				]);
				doc.addPage();
				doc.autoTable({
					startY: 10,
					head: [['Compound ID', 'SMILES', 'Formula', 'Log P', 'Polar Surface Area', 'Rotatable Bonds', 'Molecular Weight', 'Affinity Score']],
					body: compoundsData,
					styles: { fontSize: 8, font: 'helvetica' }
				});

				// Save the PDF
				doc.save('Task_Details_Report.pdf');
			} catch (error) {
				console.error('Error generating PDF:', error);
			}
		},
		async downloadResults() {
			try {
				if (this.compounds.length === 0) {
					console.warn('没有结果可下载');
					return;
				}

				// 将所有化合物信息整合成一个 CSV 文件
				const csvHeaders = ['Compound ID', 'SMILES', 'Affinity Score', 'Log P', 'PSA', 'Rotatable Bond', 'Weight'];
				const csvContent = [
					csvHeaders.join(','),
					...this.compounds.map((compound) =>
						[compound.compound_id, compound.smile, compound.affinity_score, compound.logp, compound.psa, compound.rotable_bond, compound.weight].join(',')
					)
				].join('\n');

				const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8' });
				saveAs(blob, '筛选结果.csv');
			} catch (error) {
				console.error('下载筛选结果时出错:', error);
			}
		},
		initCharts() {
			const charts = ['chart1', 'chart2', 'chart3', 'chart4'];
			const chartData = [
				{ name: '活性分数', data: this.dataList },
				{ name: 'Log P', data: this.logpvalues },
				{ name: '极性表面积', data: this.psavalues },
				{ name: '分子量', data: this.weightvalues }
			];
			charts.forEach((chartRef, index) => {
				const chart = echarts.init(this.$refs[chartRef]);
				const histogramData = this.calculateHistogram(chartData[index].data);
				const option = {
					title: {
						text: chartData[index].name,
						left: 'center',
						textStyle: {
							fontSize: 16, // 字体大小
							fontWeight: 'normal', // 字体粗细：normal（不加粗）或 bold（加粗）
							color: '#333' // 字体颜色
						}
					},
					tooltip: {
						position: 'top'
					},
					grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
					xAxis: {
						type: 'category',
						boundaryGap: true,
						data: histogramData.bins,
						axisLabel: {
							interval: 0,
							rotate: 45
						}
					},
					yAxis: {
						type: 'value',
						axisLabel: {
							formatter: '{value} %'
						}
					},
					series: [
						{
							name: '分布',
							type: 'bar',
							data: histogramData.percentages,
							barWidth: '50%',
							itemStyle: {
								normal: {
									color: '#409EFF'
								}
							}
						},
						{
							name: '趋势线',
							type: 'line',
							data: histogramData.percentages,
							smooth: true,
							lineStyle: {
								width: 3,
								color: '#7ee9d1'
							},
							symbol: 'circle',
							symbolSize: 6
						}
					]
				};
				chart.setOption(option);
			});
		},
		initHeatmap() {
			const heatmapChart = echarts.init(this.$refs.heatmap);
			const option = {
				title: {
					text: '相似度矩阵热图',
					left: 'center',
					textStyle: {
						fontSize: 16, // 字体大小
						fontWeight: 'normal', // 字体粗细：normal（不加粗）或 bold（加粗）
						color: '#333' // 字体颜色
					}
				},
				tooltip: {
					position: 'top'
				},
				grid: {
					left: '3%',
					right: '6%',
					bottom: '3%',
					containLabel: true
				},
				xAxis: {
					type: 'category',
					// data: Array.from({ length: this.similarityMatrix.length }, (_, i) => `化合物${i + 1}`),
					splitArea: {
						show: true
					}
				},
				yAxis: {
					type: 'category',
					// data: Array.from({ length: this.similarityMatrix.length }, (_, i) => `化合物${i + 1}`),
					splitArea: {
						show: true
					}
				},
				visualMap: {
					min: 0,
					max: 1,
					calculable: true,
					left: 'center'
				},
				series: [
					{
						name: '相似度',
						type: 'heatmap',
						data: this.similarityMatrix.flatMap((row, i) => row.map((value, j) => [i, j, value])),
						label: {
							show: false
						},
						emphasis: {
							itemStyle: {
								shadowBlur: 10,
								shadowColor: 'rgba(0, 0, 0, 0.5)'
							}
						}
					}
				]
			};
			heatmapChart.setOption(option);
		},
		calculateHistogram(data) {
			const bins = 10;
			const max = Math.max(...data);
			const min = Math.min(...data);
			const binWidth = (max - min) / bins;
			const histogram = new Array(bins).fill(0);

			data.forEach((value) => {
				const index = Math.min(bins - 1, Math.floor((value - min) / binWidth));
				histogram[index]++;
			});

			const total = data.length;
			const percentages = histogram.map((count) => ((count / total) * 100).toFixed(2));
			const binLabels = Array.from({ length: bins }, (_, i) => `${(min + i * binWidth).toFixed(2)}-${(min + (i + 1) * binWidth).toFixed(2)}`);

			return { bins: binLabels, percentages };
		}
	}
};
</script>

<style scoped>
/* 让 SMILES 溢出时自动换行，且不超出容器 */
.smiles-text {
	word-wrap: break-word;
	word-break: break-all;
	overflow-wrap: break-word;
	white-space: normal;
	width: 100%;
	margin-top: 10px;
}

/* Score 部分右对齐 */
.score-container {
	text-align: right;
}

.el-card {
	margin-bottom: 20px;
}

.mol-description {
	text-align: center;
}
.mol-container {
	width: 350px;
	height: 400px;
	position: relative;
}

.task-details-container {
	padding: 20px;
	font-family: Arial, sans-serif;
}
.task-details-row {
	margin-bottom: 40px;
}
.task-details-card {
	padding: 10px;
	border-radius: 8px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.buttons {
	margin-top: 20px;
	display: flex;
	gap: 10px;
}
.table-section {
	margin-top: 40px;
}
.pagination {
	margin-top: 20px;
	text-align: center;
}
.compound-info {
	font-size: 16px;
}
.charts-section {
	margin-top: 20px;
}
</style>
